/* Copyright 2007 Gearbox Software - http://www.gearboxsoft.com
 
 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at
 
     http:www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.*/
namespace GearBlog.Web.Utils
{
	using System;
	using System.Collections.Specialized;
	using System.Text;
	using Castle.MonoRail.Framework;
	using GearBlog.Web.Models;

	public class HttpAuthenticationAgent:AuthenticationAgentBase
	{
		
		public override bool AttemptLogin(Controller controller, string returnUrl)
		{
			
			OrderedDictionary credential = RetrieveCredentials(controller);
			bool result=false ;
			if (credential != null)
				 result = Authenticate(credential, controller);
			if (!result)
			{
				Setting setting = Setting.FindFirst();
				controller.Response.ClearContent();
				controller.Response.StatusCode = 401;
				controller.Response.AppendHeader("WWW-Authenticate", string.Format("BASIC Realm=\"{0}\"", setting.Title));
			}
			return result;
		}

		public override void ShowAccessDenied(Controller controller)
		{
			FormsAuthenticationAgent agent=new FormsAuthenticationAgent();
			agent.ShowAccessDenied(controller);
		}
		
		private static OrderedDictionary RetrieveCredentials(Controller controller)
		{
			string authToken = controller.Request.Params["HTTP_AUTHORIZATION"];
			OrderedDictionary credential = ParseAuthToken(authToken);
			if (credential != null && !string.IsNullOrEmpty((string)credential["UserName"]))
				return credential;
			else
				return null;
				
		}
		private static OrderedDictionary ParseAuthToken(string authToken)
		{
			if (!string.IsNullOrEmpty(authToken))
			{
				OrderedDictionary credential = new OrderedDictionary();
				string[] authTokenSet = authToken.Split(' ');
				credential.Add("Mode", authTokenSet[0]);
				string[] credentialSet = Base64Decode(authTokenSet[1]).Split(':');
				if (credentialSet[0].Length > 0)
				{
					credential.Add("UserName", credentialSet[0]);
					credential.Add("Password", credentialSet[1]);
				}
				return credential;
			}
			else
				return null;

		}
		private static string Base64Decode(string EncodedData)
		{
			try
			{
				UTF8Encoding encoder = new UTF8Encoding();
				Decoder utf8Decode = encoder.GetDecoder();
				byte[] todecode_byte = Convert.FromBase64String(EncodedData);
				int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
				char[] decoded_char = new char[charCount];
				utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
				return new String(decoded_char);
			}
			catch (Exception e)
			{
				throw new Exception("Error in base64Decode" + e.Message);
			}
		}
		private static bool Authenticate(OrderedDictionary credential, Controller controller)
		{
			return SecurityUtil.Authenticate(controller, (string) credential["UserName"], (string) credential["Password"], false, string.Empty);
		}
	}
}
